import { MongodbClient } from "../lib/db.client.mongodb";
import { PgClient } from "../lib/db.client.pg";

import { Contact, ENUM_TON_ORDER, RefTonOrderStamp, TonOrder, TonOrderGroup, User } from "qqlx-core";
import { getConditionMatchStrOrs, getConditionMatchStr, TonOrderSchema, getConditionMatchEnum, RefTonOrderStampSchema } from "qqlx-cdk";

import { User as OldUser } from "../../../qqlx.old/qqlx-core";
import { Corp as OldCorp } from "../../../qqlx.old/qqlx-core";
import { Contact as OldContact } from "../../../qqlx.old/qqlx-core";
import { Order as OldOrder, ENUM_ORDER } from "../../../qqlx.old/qqlx-core";

import { getTradeId } from "../lib/crypto";
import { TonOrderDao, RefTonOrderStampDao } from "../dao/river";
import { doBashPrint } from "../lib/log";
import { ObjectId } from "mongodb";

export async function doTonOrderAdjustInsert(
  corpId: OldCorp["_id"],
  oldToNewUserMap: Map<OldUser["_id"], User>,
  oldContactMap: Map<OldContact["_id"], Contact>,
  userOrderGroupMap: Map<User["uuid32"], TonOrderGroup>,
) {
  const mongodbClient = new MongodbClient("mongodb://localhost:27017/qqlx");
  const pgClient = new PgClient("127.0.0.1", "5432", "production", "postgres", "postgres");

  /** 根据采购订单_id 寻找新订单 */
  const oldToNewAdjustMap = new Map<OldUser["_id"], TonOrder>();

  try {
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================
    // ==================== 旧数据准备 ====================

    console.group("\n开始迁移mongo库存调整订单数据");
    const mongoBefore = { count: 0 };
    const mongoChange = { count: 0 };

    await mongodbClient.start();
    const pgClientIns = await pgClient.start();

    const colCorps = mongodbClient.getCollection("corps");
    const corp = (await colCorps.findOne<OldCorp>({ _id: corpId as unknown as ObjectId })) as OldCorp;
    const corpQuery = { corpId: corp._id as unknown as ObjectId };

    const colOrders = mongodbClient.getCollection("orders");
    const purchaseQuery = { ...corpQuery, type: ENUM_ORDER.GETIN, parentOrderId: "" };
    const oldOrders = await colOrders.find<OldOrder>(purchaseQuery).toArray();

    console.log("旧数据（库存调整订单）", oldOrders.length);
    mongoBefore.count += oldOrders.length;

    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================
    // ==================== 新数据准备 ====================

    const orderDao = new TonOrderDao(pgClientIns.getRepository<TonOrder>(TonOrderSchema));
    const stampDao = new RefTonOrderStampDao(pgClientIns.getRepository<RefTonOrderStamp>(RefTonOrderStampSchema));

    const master = oldToNewUserMap.get(corp.userId) as User;
    const condis = [getConditionMatchStr("refOwnerUUid32", master.uuid32)];
    const groupExist = userOrderGroupMap.get(master.uuid32) as TonOrderGroup;

    // 迁移库存调整订单
    const condis2 = [...condis, getConditionMatchEnum("type", ENUM_TON_ORDER.ADJUST)];
    const tonOrderCount = await orderDao.count(condis2);
    if (tonOrderCount === 0) {
      const tonOrderSchemaLs = oldOrders.map((oldGetin) => {
        const schema = getDefaultOrder(oldGetin, master.uuid32);

        const creatorCache = oldToNewUserMap.get(oldGetin.creatorId) as User;
        if (!creatorCache) throw { message: `创建人异常：${oldGetin.creatorId}` };
        schema.refCreatorId = creatorCache.uuid32;

        const contactCache = oldContactMap.get(oldGetin.contactId) || oldContactMap.get(`${master.uuid32}:contact:unknown`);
        if (contactCache?.refOwnerUUid32 !== master.uuid32) {
          throw { message: `联系人异常：${oldGetin.contactId}` };
        }

        schema.refContactId = contactCache.id;
        schema.tradeId = getTradeId();
        schema.tradeTime = oldGetin.timeCreate.toString();
        schema.tradeYear = new Date(oldGetin.timeCreate).getFullYear();
        schema.tradeMonth = new Date(oldGetin.timeCreate).getMonth() + 1;
        schema.tradeScope = `${master.uuid32}-${groupExist.id}`;

        schema.refTonOrderGroupId = groupExist.id;
        schema.contractSideOp = contactCache.name;
        schema.contractTime = oldGetin.timeContract.toString();

        schema.content = oldGetin._id; // 用于存储历史订单id
        return schema;
      });

      // 批量插入订单
      const batchCount = 2000;
      const createds: TonOrder[] = [];
      while (tonOrderSchemaLs.length > 0) {
        const part = tonOrderSchemaLs.splice(0, batchCount);
        const ls = await orderDao.insertManyAndQuery(part);
        createds.push(...ls);
        doBashPrint(`正在推送订单（${batchCount}）剩余${tonOrderSchemaLs.length}`);
      }
      mongoChange.count += createds.length;
    }

    // 缓存数据
    const oids = oldOrders.map((c) => c._id);
    const condis3 = [...condis2, getConditionMatchStrOrs("content", oids)];
    const orderAll = await orderDao.queryAll(condis3);
    orderAll.list.map((exist) => oldToNewAdjustMap.set(exist.content, exist));

    // ==================== 结束 ====================
    // ==================== 结束 ====================
    // ==================== 结束 ====================
    // ==================== 结束 ====================
    // ==================== 结束 ====================
    // ==================== 结束 ====================

    const pgCountFinal = await orderDao.count(condis2);
    console.log(`mg目标迁移数字🔴期望/已迁移`, mongoBefore.count, mongoChange.count);
    console.log(`pg数据库记录🟢变动前/变动后`, tonOrderCount, pgCountFinal, "变动误差", pgCountFinal - tonOrderCount);
    console.groupEnd();
    console.log("====================================");
  } finally {
    await pgClient.stop();
    await mongodbClient.stop();
  }

  return { oldToNewAdjustMap };
}

function getDefaultOrder(old: OldOrder, masterId: User["uuid32"]) {
  const schema: TonOrder = new TonOrderSchema();
  schema.isDisabled = old.isDisabled;
  schema.timeCreate = old.timeCreate.toString();
  schema.timeUpdate = old.timeUpdate.toString();
  schema.type = ENUM_TON_ORDER.ADJUST;

  schema.refOwnerUUid32 = masterId;
  schema.remark = old.remark;
  schema.code = old.code;
  return schema;
}
